import { computed, ref, shallowReactive } from 'vue';
import { useEventSource } from '@boeyo/hooks';
import { IconFont, useUserStore } from '@boeyo/portal';
import { download } from '@boeyo/shared';
import { Button, Divider, Modal, Steps, StepsProps } from 'ant-design-vue';

interface Opt {
  title: string;
  url: string;
  data: any;
  method?: string;
  onClose?: () => void;
}

interface Data {
  fileName: string;
  data: string;
}

export const useSseModal = () => {
  const option = shallowReactive<Opt>({
    title: '',
    url: '',
    data: {},
    method: '',
  });

  const title = computed(() => option.title);
  const url = computed(() => option.url);
  const data = computed<any>(() => option.data);
  const method = computed<'GET' | 'POST' | 'PUT' | 'DELETE'>(
    () => (option.method || 'POST') as any,
  );
  const visible = ref<boolean>(false);
  const userStore = useUserStore();
  const device = ref<Record<string, any>>({});

  const onDownload = (data: Data) => {
    download(new Blob([data.data], { type: 'text/plain' }), data.fileName);
  };

  const items = computed<
    Array<{
      key: string;
      values: StepsProps['items'];
    }>
  >(() => {
    return Object.keys(device.value).map((key) => {
      return {
        key: key,
        values: device.value[key].map((item) => {
          return {
            title: item.data?.fileName ? (
              <span>
                <span> {item.msg} </span>
                <Button type='link' onClick={() => onDownload(item.data)}>
                  <IconFont type='icon_export' />
                  <span>下载</span>
                </Button>
              </span>
            ) : (
              item.msg
            ),
            description: item.date,
            status: getStatus(item.code),
          };
        }),
      };
    });
  });
  const getStatus = (code: number): StepsProps['status'] => {
    switch (code) {
      case 201:
        return 'process';
      case 200:
        return 'finish';
      case 500:
        return 'error';
    }
  };

  const handleMessage = (data) => {
    console.log(data);
    if (device.value[data.key]) {
      device.value[data.key].push(data);
    } else {
      device.value[data.key] = [data];
    }
  };

  const _opt = computed(() => {
    const contentType =
      data.value instanceof FormData ? '' : 'application/json';

    const headers = {
      ['Authorization']: `Bearer ${userStore.token}`,
      Accept: '*/*',
    };
    if (contentType) {
      Object.assign(headers, { 'Content-Type': contentType });
    }

    return {
      headers,
      withCredentials: false,
      method: method.value,
      body: data,
      onMessage(res) {
        const data = JSON.parse(res);
        handleMessage(data);
      },
    };
  });

  const { connect, disconnect } = useEventSource(url, _opt);

  const open = (opt: Opt) => {
    Object.assign(option, opt);
    visible.value = true;
    connect();
  };
  const onClose = () => {
    device.value = {};
    disconnect();
    option.onClose?.();
    visible.value = false;
    Object.assign(option, { title: '', url: '', data: {}, method: '' });
  };

  const SseModal = () => {
    return (
      <Modal
        title={title.value}
        destroyOnClose
        keyboard={false}
        maskClosable={false}
        width='60%'
        afterClose={() => onClose()}
        onCancel={() => (visible.value = false)}
        open={visible.value}
        footer={null}
      >
        <div class='sse-wrap w-full overflow-x-auto py-4'>
          {items.value.map((item) => {
            return (
              <>
                <Divider orientation='left'>{item.key}</Divider>
                <Steps
                  items={item.values}
                  current={item.values.length - 1}
                  size='small'
                />
              </>
            );
          })}
        </div>
      </Modal>
    );
  };

  return {
    open,
    SseModal,
  };
};
